From: Matthieu Gallien Date: Mon, 17 Feb 2025 17:52:54 +0000 (+0100) Subject: prevent infinite sync loop: delay retry after many errors X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~2^2~45^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/www.github.com/%22bookmarks:///%22http:/www.example.com/cgi/%22https:/www.github.com/%22bookmarks:/?a=commitdiff_plain;h=5212df870cb45f82346f5b3e91a3beee31073bdf;p=nextcloud-desktop.git prevent infinite sync loop: delay retry after many errors 10 seconds for try 3 and 4 30 seconds for try 5 and 6 60 seconds for more Signed-off-by: Matthieu Gallien --- diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 6f84af9ad..c9b7faaea 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -719,21 +719,49 @@ void FolderMan::scheduleFolder(Folder *f) qCInfo(lcFolderMan) << "Schedule folder " << alias << " to sync!"; + auto syncAgainDelay = std::chrono::seconds(0); + if (f->consecutiveFailingSyncs() > 2 && f->consecutiveFailingSyncs() <= 4) { + syncAgainDelay = std::chrono::seconds(10); + } else if (f->consecutiveFailingSyncs() > 4 && f->consecutiveFailingSyncs() <= 6) { + syncAgainDelay = std::chrono::seconds(30); + } else if (f->consecutiveFailingSyncs() > 6) { + syncAgainDelay = std::chrono::seconds(60); + } + if (!_scheduledFolders.contains(f)) { if (!f->canSync()) { qCInfo(lcFolderMan) << "Folder is not ready to sync, not scheduled!"; _socketApi->slotUpdateFolderView(f); return; } - f->prepareToSync(); - emit folderSyncStateChange(f); - _scheduledFolders.enqueue(f); - emit scheduleQueueChanged(); + + if (syncAgainDelay == std::chrono::seconds(0)) { + f->prepareToSync(); + emit folderSyncStateChange(f); + _scheduledFolders.enqueue(f); + emit scheduleQueueChanged(); + startScheduledSyncSoon(); + } else { + qCWarning(lcFolderMan()) << "going to delay the next sync run due to too many synchronization errors" << syncAgainDelay; + QTimer::singleShot(syncAgainDelay, this, [this, f] () { + f->prepareToSync(); + emit folderSyncStateChange(f); + _scheduledFolders.enqueue(f); + emit scheduleQueueChanged(); + startScheduledSyncSoon(); + }); + } } else { qCInfo(lcFolderMan) << "Sync for folder " << alias << " already scheduled, do not enqueue!"; + if (syncAgainDelay == std::chrono::seconds(0)) { + startScheduledSyncSoon(); + } else { + qCWarning(lcFolderMan()) << "going to delay the next sync run due to too many synchronization errors" << syncAgainDelay; + QTimer::singleShot(syncAgainDelay, this, [this] () { + startScheduledSyncSoon(); + }); + } } - - startScheduledSyncSoon(); } void FolderMan::scheduleFolderForImmediateSync(Folder *f) diff --git a/test/testfolderman.cpp b/test/testfolderman.cpp index c83737828..fa01cb51a 100644 --- a/test/testfolderman.cpp +++ b/test/testfolderman.cpp @@ -37,7 +37,7 @@ class TestFolderMan: public QObject { Q_OBJECT - FolderMan _fm; + std::unique_ptr _fm; signals: void incomingShareDeleted(); @@ -53,6 +53,9 @@ private slots: void testDeleteEncryptedFiles() { + _fm.reset({}); + _fm.reset(new FolderMan{}); + FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; QCOMPARE(fakeFolder.currentLocalState().children.count(), 4); @@ -154,6 +157,9 @@ private slots: void testLeaveShare() { + _fm.reset({}); + _fm.reset(new FolderMan{}); + QTemporaryDir dir; ConfigFile::setConfDir(dir.path()); // we don't want to pollute the user's config file @@ -182,7 +188,7 @@ private slots: secondShare->permissions.setPermission(OCC::RemotePermissions::IsShared); FolderMan *folderman = FolderMan::instance(); - QCOMPARE(folderman, &_fm); + QCOMPARE(folderman, _fm.get()); OCC::AccountState *accountState = OCC::AccountManager::instance()->accounts().first().data(); const auto folder = folderman->addFolder(accountState, folderDefinition(fakeFolder.localPath())); QVERIFY(folder); @@ -252,6 +258,9 @@ private slots: void testCheckPathValidityForNewFolder() { + _fm.reset({}); + _fm.reset(new FolderMan{}); + #ifdef Q_OS_WIN Utility::NtfsPermissionLookupRAII ntfs_perm; #endif @@ -278,7 +287,7 @@ private slots: AccountStatePtr newAccountState(new AccountState(account)); FolderMan *folderman = FolderMan::instance(); - QCOMPARE(folderman, &_fm); + QCOMPARE(folderman, _fm.get()); QVERIFY(folderman->addFolder(newAccountState.data(), folderDefinition(dirPath + "/sub/ownCloud1"))); QVERIFY(folderman->addFolder(newAccountState.data(), folderDefinition(dirPath + "/ownCloud2"))); @@ -382,6 +391,9 @@ private slots: void testFindGoodPathForNewSyncFolder() { + _fm.reset({}); + _fm.reset(new FolderMan{}); + // SETUP QTemporaryDir dir; @@ -405,7 +417,7 @@ private slots: AccountStatePtr newAccountState(new AccountState(account)); FolderMan *folderman = FolderMan::instance(); - QCOMPARE(folderman, &_fm); + QCOMPARE(folderman, _fm.get()); QVERIFY(folderman->addFolder(newAccountState.data(), folderDefinition(dirPath + "/sub/ownCloud/"))); QVERIFY(folderman->addFolder(newAccountState.data(), folderDefinition(dirPath + "/ownCloud2/")));